/**
 * Package Name:cn.com.guodiantong.common.service
 * Date:2017年8月14日 下午3:48:26
 * Copyright (c) 2017 mr.luoxing@gmail.com Rights Reserved.
 *
 */

package cn.com.guodiantong.common.api.aspect;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.com.guodiantong.common.api.domain.LoggerModel;
import cn.com.guodiantong.common.api.service.ILoggerService;

/**
 * @ClassName: LoggerAspect.<br/>
 * @Description: TODO(日志拦截类).<br/>
 *
 * @author Mr.Luoxing
 * @version 1.0.0
 */
@Aspect
@Component
@Order(-5)
public class LoggerAspect {

	private static final Logger logger = LoggerFactory.getLogger(LoggerAspect.class);
	
	@Autowired
	ILoggerService service;
	
	@Pointcut("@annotation(cn.com.guodiantong.common.api.annotation.Logger)")
	public void serviceAspect() {}
	
	@After("serviceAspect()")
	public void doAfter(JoinPoint joinPoint) throws Exception {
		// 接收到请求，记录请求内容
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		
		// 记录下请求内容
		logger.info("URL : " + request.getRequestURL().toString());
		logger.info("HTTP_METHOD : " + request.getMethod());
		logger.info("IP : " + request.getRemoteAddr());
		logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
		logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
		//获取所有参数方法一：
        Enumeration<String> enu=request.getParameterNames(); 
        while(enu.hasMoreElements()){ 
            String paraName=(String)enu.nextElement(); 
            System.out.println(paraName+": "+request.getParameter(paraName)); 
        } 

		try {
            //*========控制台输出=========*//
             System.out.println("=====后置通知开始=====");
             System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
             System.out.println("方法描述:" + getServiceMethodDescription(joinPoint));
             
             cn.com.guodiantong.common.api.annotation.Logger log = getServiceMethodDescription(joinPoint);
             LoggerModel model = new LoggerModel();
             model.setId(UUID.randomUUID().toString().toUpperCase());
             model.setModule(log.module());
             model.setContent(log.note());
             model.setMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
             model.setParam(Arrays.toString(joinPoint.getArgs()));
             model.setIp(request.getRemoteAddr());
             model.setUrl(request.getRequestURL().toString());
             model.setType(log.type().getValue());
             model.setUid(UUID.randomUUID().toString().toUpperCase());
             model.setDate(new Date());
             service.save(model);
             
        }  catch (Exception e) {
            logger.error("==后置通知异常==");
            logger.error("异常信息:{}", e.getMessage());
        }
	}
	
	/**
     * 异常通知 用于拦截service层记录异常日志
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        try {
            /*========控制台输出=========*/
             System.out.println("=====异常通知开始=====");
             System.out.println("异常代码:" + e.getClass().getName());
             System.out.println("异常信息:" + e.getMessage());
             System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
             System.out.println("方法描述:" + getServiceMethodDescription(joinPoint));
        }  catch (Exception ex) {
            //记录本地异常日志
            logger.error("==异常通知异常==");
            logger.error("异常信息:{}", ex.getMessage());
        }

    }

	
	 /**
     * 获取注解中对方法的描述信息 用于service层注解
     *
     * @param joinPoint 切点
     * @return 方法描述
     * @throws Exception
     */
    @SuppressWarnings({ "rawtypes"})
	private static cn.com.guodiantong.common.api.annotation.Logger getServiceMethodDescription(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
//        String description = "";
        cn.com.guodiantong.common.api.annotation.Logger logger = null;
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
//                    description = method.getAnnotation(cn.com.guodiantong.common.api.annotation.Logger.class).note();
                    logger = method.getAnnotation(cn.com.guodiantong.common.api.annotation.Logger.class);
                    break;
                }
            }
        }
        return logger;
    }
}

